﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using NLog;
using System.IO.Ports;
using HalconDotNet;
using GeneralMotionControlProject.Vision.Models.Display;
using GeneralMotionControlProject.Vision.Models;
using Newtonsoft.Json;

namespace ModuleBase
{
    public class VisionResult
    {
        public int PcsOrder;
        public VResult result;//0:未做模板 1:没找到 2:超限 200:PASS
        public double deltaX;
        public double deltaY;
        public double deltaAngle;
        public HObject r_image;//计算图片
        public HObject r_region;
        public HObject r_recScale;
        public HTuple r_row;//焊接位置
        public HTuple r_column;
        public string r_name;
        public string r_additional_msg;
        public VisionResult()
        {
            PcsOrder = 0;
            result = VResult.Null;
            deltaX = 0;
            deltaY = 0;
            deltaAngle = 0;
            r_additional_msg = string.Empty;
        }
    }
    public struct MMarkResult
    {
        public bool Result;
        public double Row;
        public double Column;
    }

    public enum VResult
    {
        Null,
        NG,
        Limit,
        PASS = 200
    }


    public static class MFunc
    {
        private static Logger logger = LogManager.GetCurrentClassLogger();
        [DllImport("halcon.dll")]
        public static extern void HIOCancelDraw();//退出画操作时，调用此函数
        public static string LazerScript(string ip, string cmdstr, int port = 13000, bool isReceive = false)
        {
            try
            {
                using (TcpClient client = new TcpClient())
                {

                    var result = client.BeginConnect(ip, port, null, null);

                    var success = result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(1));

                    if (!success)
                    {
                        throw new Exception("Failed to connect.");
                    }

                    client.EndConnect(result);

                    // Translate the passed message into ASCII and store it as a Byte array.
                    byte[] data = System.Text.Encoding.ASCII.GetBytes(cmdstr);

                    // Get a client stream for reading and writing.
                    //  Stream stream = client.GetStream();

                    NetworkStream stream = client.GetStream();

                    // Send the message to the connected TcpServer.
                    stream.Write(data, 0, data.Length);

                    stream.ReadTimeout = 3000;
                    // String to store the response ASCII representation.
                    string responseData = string.Empty;
                    if (isReceive)
                    {
                        // Buffer to store the response bytes.
                        data = new byte[256];
                        // Read the first batch of the TcpServer response bytes.
                        int bytes = stream.Read(data, 0, data.Length);
                        responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
                    }
                    // Close everything.
                    stream.Close();
                    client.Close();
                    return responseData;
                }
            }
            catch (Exception ex)
            {
                logger.Info($"{ip}:{cmdstr}");
                logger.Error(ex);
                return string.Empty;
            }
        }
        public static string LazerScriptPD(string ip, string cmdstr, string paramstr, int port = 13000)
        {
            try
            {
                using (TcpClient client = new TcpClient())
                {

                    var result = client.BeginConnect(ip, port, null, null);

                    var success = result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(1));

                    if (!success)
                    {
                        throw new Exception("Failed to connect.");
                    }

                    client.EndConnect(result);
                    // Translate the passed message into ASCII and store it as a Byte array.
                    byte[] data = System.Text.Encoding.ASCII.GetBytes(cmdstr);

                    // Get a client stream for reading and writing.
                    //  Stream stream = client.GetStream();

                    NetworkStream stream = client.GetStream();

                    // Send the message to the connected TcpServer.
                    stream.Write(data, 0, data.Length);

                    stream.ReadTimeout = 3000;
                    // String to store the response ASCII representation.
                    string responseData = string.Empty;
                    // Buffer to store the response bytes.
                    data = new byte[256];
                    // Read the first batch of the TcpServer response bytes.
                    int bytes = stream.Read(data, 0, data.Length);
                    //读速度参数
                    data = System.Text.Encoding.ASCII.GetBytes(paramstr);
                    stream.Write(data, 0, data.Length);
                    data = new byte[256];
                    bytes = stream.Read(data, 0, data.Length);

                    responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);

                    // Close everything.
                    stream.Close();
                    client.Close();
                    return responseData;
                }
            }
            catch (Exception ex)
            {
                logger.Info($"{ip}:{cmdstr}");
                logger.Error(ex);
                return string.Empty;
            }
        }
        public static void Send2Lazer(string com, string str)
        {
            // 创建串口对象
            SerialPort serialPort = new SerialPort(com, 9600, Parity.None, 8, StopBits.One);

            // 打开串口
            serialPort.Open();

            // 发送数据
            //string data = "TP0:1.2,0.5,9.5;";
            byte[] bytes = Encoding.UTF8.GetBytes(str); // 将字符串转换为字节数组
            serialPort.Write(bytes, 0, bytes.Length); // 发送字节数组

            // 关闭串口
            serialPort.Close();
        }

        public static void VisionAction(MDbContext mdb, MVisionFunctions mVisionFunctions, string procedureName, HObject img, out HTuple row,
            out HTuple column, out HTuple angle, out HTuple result, out HObject r_region, out string additionalMessage)
        {
            result = new HTuple(0);
            try
            {
                VisionProgramDisp disp = JsonConvert.DeserializeObject<VisionProgramDisp>(procedureName);
                int id = disp.Id;
                HOperatorSet.GetImageSize(img, out var hv_Width, out var hv_Height);
                HTuple hv_row = new HTuple(0), hv_column = new HTuple(0), hv_angle = new HTuple(0), hv_score = new HTuple(0), v1 = new HTuple(0), v2 = new HTuple(0);
                string msg = string.Empty;
                HObject eImage = img.CopyObj(1, -1);
                HObject ngRegion, resultRegion;
                HOperatorSet.GenEmptyObj(out ngRegion);
                HOperatorSet.GenEmptyObj(out r_region);
                HOperatorSet.GenEmptyObj(out resultRegion);
                bool r1 = true;
                var projects = mdb.VisionProjects.Where(pro => pro.ProgramId == id).OrderBy(pro => pro.PcsOrder);
                if (projects.Any())
                {
                    var mprojects = projects.ToList();
                    foreach (var project in mprojects)
                    {
                        if (!r1)
                        {
                            break;
                        }
                        var _function = mVisionFunctions.VisionFunctions.FirstOrDefault(func => func.Id == project.FunctionId);
                        if (_function != null)
                        {
                            HObject SelectedRegion;
                            HOperatorSet.GenEmptyObj(out SelectedRegion);
                            r1 = mVisionFunctions.FunDictionary[_function.Name].Run(ref eImage, project.Parameter, ref hv_row, ref hv_column, ref hv_angle, ref hv_score, ref ngRegion, ref SelectedRegion, ref v1, ref v2, ref msg);
                            if (project.IsDisplayRegion)
                            {
                                HOperatorSet.Union2(resultRegion, SelectedRegion.CopyObj(1, -1), out resultRegion);
                            }
                            SelectedRegion.Dispose();
                        }
                        else
                        {
                            r1 = false;
                        }
                    }
                }
                else
                {
                    r1 = false;
                }
                if (r1)
                {
                    result = new HTuple(1);
                    row = hv_row;
                    column = hv_column;
                    angle = hv_angle;
                    r_region = resultRegion.CopyObj(1, -1);
                }
                else
                {
                    result = new HTuple(0);
                    row = new HTuple(0);
                    column = new HTuple(0);
                    angle = new HTuple(0);
                }
                additionalMessage = msg;
                eImage.Dispose();
                ngRegion.Dispose();
                resultRegion.Dispose();
            }
            catch (Exception ex)
            {
                logger.Error(ex);
                result = new HTuple(0);
                row = new HTuple(0);
                column = new HTuple(0);
                angle = new HTuple(0);
                HOperatorSet.GenEmptyRegion(out r_region);
                additionalMessage = string.Empty;
            }

        }
    }
    public class MRec
    {
        public double Row1 { get; set; }
        public double Column1 { get; set; }
        public double Row2 { get; set; }
        public double Column2 { get; set; }
        public double Width { get; set; }
        public double Height { get; set; }
    }
}
